#!/bin/bash
# Elasticsearch 8.6.0 系统环境初始化脚本
# 适用于 CentOS/RHEL 7+ 及其他 Linux 发行版
# 必须以 root 用户权限运行

set -e # 遇到任何错误立即退出

LOG_FILE="/var/log/es-init.log"
ES_USER="elasticsearch"
ES_GROUP="elasticsearch"
ES_HOME="/usr/local/elasticsearch" # 假设的ES安装目录

# 颜色输出定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 日志记录函数
log_info() {
    echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
    exit 1
}

# 检查 root 权限
check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "此脚本必须以 root 权限运行"
    fi
}

# 检查操作系统
check_os() {
    if [ -f /etc/redhat-release ]; then
        OS="centos"
    elif [ -f /etc/debian_version ]; then
        OS="debian"
    else
        log_warn "未知的操作系统，脚本可能无法正常工作"
    fi
}

# 安装必要的系统工具
install_tools() {
    log_info "安装必要的系统工具 (wget, tar等)"
    if [ "$OS" = "centos" ]; then
        yum install -y wget tar >> "$LOG_FILE" 2>&1 || log_warn "安装系统工具时遇到问题"
    elif [ "$OS" = "debian" ]; then
        apt-get update && apt-get install -y wget tar >> "$LOG_FILE" 2>&1 || log_warn "安装系统工具时遇到问题"
    fi
}

# 创建 Elasticsearch 用户和组
create_es_user() {
    if id -u "$ES_USER" >/dev/null 2>&1; then
        log_info "用户 $ES_USER 已存在"
    else
        log_info "创建用户和组: $ES_USER"
        groupadd "$ES_GROUP" >> "$LOG_FILE" 2>&1 || log_error "创建组 $ES_GROUP 失败"
        useradd -M -s /bin/bash --gid "$ES_GROUP" "$ES_USER" >> "$LOG_FILE" 2>&1 || log_error "创建用户 $ES_USER 失败"
    fi
}

# 调整系统内核参数
configure_kernel() {
    log_info "配置系统内核参数"

    # 调整 vm.max_map_count
    if grep -q "vm.max_map_count" /etc/sysctl.conf; then
        log_info "vm.max_map_count 参数已存在，更新值"
        sed -i 's/vm.max_map_count=.*/vm.max_map_count=262144/' /etc/sysctl.conf
    else
        echo "vm.max_map_count=262144" >> /etc/sysctl.conf
    fi

    # 应用配置
    sysctl -p >> "$LOG_FILE" 2>&1 || log_error "应用 sysctl 配置失败"
}

# 配置资源限制
configure_limits() {
    log_info "配置用户资源限制"

    if ! grep -q "$ES_USER" /etc/security/limits.conf; then
        cat >> /etc/security/limits.conf << EOF
# Elasticsearch 用户资源限制
$ES_USER soft nofile 65535
$ES_USER hard nofile 65535
$ES_USER soft nproc 4096
$ES_USER hard nproc 4096
$ES_USER soft memlock unlimited
$ES_USER hard memlock unlimited
EOF
        log_info "已添加资源限制"
    else
        log_info "资源限制已存在"
    fi
}

# 创建数据目录并设置权限
create_directories() {
    log_info "创建 Elasticsearch 数据目录并设置权限"

    local DATA_DIR="/data/elasticsearch/8.6.0/data/"
    local LOG_DIR="/data/elasticsearch/8.6.0/logs/"

    mkdir -p "$DATA_DIR" "$LOG_DIR"
    chown -R "$ES_USER:$ES_GROUP" "$DATA_DIR" "$LOG_DIR"
    chmod -R 755 "$DATA_DIR" "$LOG_DIR"

    log_info "数据目录: $DATA_DIR"
    log_info "日志目录: $LOG_DIR"
}

# 验证环境
validate_environment() {
    log_info "验证环境配置"

    # 检查用户
    if id "$ES_USER" >/dev/null 2>&1; then
        log_info "用户 $ES_USER 存在"
    else
        log_error "用户 $ES_USER 不存在"
    fi

    # 检查最大映射计数
    local MAP_COUNT
    MAP_COUNT=$(sysctl -n vm.max_map_count)
    if [ "$MAP_COUNT" -ge 262144 ]; then
        log_info "vm.max_map_count 值正确: $MAP_COUNT"
    else
        log_warn "vm.max_map_count 值可能过低: $MAP_COUNT"
    fi
}

# 输出后续步骤说明
print_next_steps() {
    cat << EOF

${GREEN}Elasticsearch 系统环境初始化完成！${NC}

${YELLOW}后续步骤：${NC}
1. 下载 Elasticsearch 8.6.0 安装包：
   wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.6.0-linux-x86_64.tar.gz

2. 解压到安装目录：
   tar -xzf elasticsearch-8.6.0-linux-x86_64.tar.gz -C $ES_HOME --strip-components=1

3. 更改目录所有权：
   chown -R $ES_USER:$ES_GROUP $ES_HOME

4. 修改 Elasticsearch 配置文件 (config/elasticsearch.yml)：
   - 设置 network.host: 0.0.0.0
   - 设置 cluster.initial_master_nodes: ["node-1"]

5. 启动 Elasticsearch：
   sudo -u $ES_USER $ES_HOME/bin/elasticsearch -d

6. 验证安装：
   curl -X GET "http://localhost:9200/"

${YELLOW}注意：${NC}
- 生产环境建议配置 SSL/TLS 加密和身份验证[8,9](@ref)。
- 确保服务器内存充足，建议至少 4GB[8,9](@ref)。
- 防火墙需开放端口 9200 (HTTP) 和 9300 (集群通信)。

EOF
}

# 主执行函数
main() {
    log_info "开始 Elasticsearch 8.6.0 系统环境初始化"
    check_root
    check_os
    install_tools
    create_es_user
    configure_kernel
    configure_limits
    create_directories
    validate_environment
    log_info "环境初始化完成！详细日志见: $LOG_FILE"
    print_next_steps
}

# 执行主函数
main "$@"
